home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000
/
Ham Radio 2000.iso
/
ham2000
/
tcp_ip
/
jnos
/
jnos_src
/
ftpserv.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-17
|
28KB
|
903 lines
/* Internet FTP Server server machine - see RFC 959
* Copyright 1991 Phil Karn, KA9Q
*/
#include <ctype.h>
#include <time.h>
#ifdef __TURBOC__
#include <io.h>
#include <dir.h>
#endif
#ifdef LINUX
#include <sys/types.h>
#include <sys/stat.h>
#endif
#include "global.h"
#include "mbuf.h"
#include "socket.h"
#include "ftp.h"
#include "ftpserv.h"
#include "proc.h"
#include "dirutil.h"
#include "files.h"
#include "commands.h"
#include "config.h"
#include "cmdparse.h"
#include "mailutil.h"
#ifdef LZW
#include "lzw.h"
#endif
static void ftpserv __ARGS((int s,void *unused,void *p));
static int pport __ARGS((struct sockaddr_in *sock,char *arg));
static void ftplogin __ARGS((struct ftpserv *ftp,char *pass));
static int sendit __ARGS((struct ftpserv *ftp,char *command,char *file));
static int recvit __ARGS((struct ftpserv *ftp,char *command,char *file));
static void sendmsgfile __ARGS((int s,int num,char *buf,int size,FILE *fp));
int doftptdisc __ARGS((int argc, char *argv[], void *p));
#ifdef FTPSERVER
extern char System[];
int FtpUsers;
/* Command table */
static char *commands[] = {
"user",
"acct",
"pass",
"type",
"list",
"cwd",
"dele",
"name",
"quit",
"retr",
"stor",
"port",
"nlst",
"pwd",
"xpwd", /* For compatibility with 4.2BSD */
"mkd ",
"xmkd", /* For compatibility with 4.2BSD */
"xrmd", /* For compatibility with 4.2BSD */
"rmd ",
"stru",
"mode",
"rsme", /* Added by IW0CNB, for resuming interrupted trasnfers */
"rput",
"noop", /* For OS/2 compatibility kf5mg*/
"syst",
#ifdef LZW
"xlzw", /* LZW FTP Compression kf5mg*/
#endif
NULLCHAR
};
/* Response messages */
static char banner[] = "220- %s, JNOS FTP version %s\n";
static char banner1[] = "220 Ready on %s";
static char badcmd[] = "500 Unknown command\n";
static char binwarn[] = "100 Warning: type is ASCII and %s appears to be binary\n";
static char unsupp[] = "500 Unsupported command or option\n";
static char AnonymousLogin[] = "331- Anonymous login OK. Please give e-mail address as password!\n";
static char givepass[] = "331 Enter PASS command\n";
/* static char challenge[] = "399 PASS challenge : %016lx\r\n"; */
static char logged[] = "230 Logged in\n";
static char loggeda[] = "230 Logged in as anonymous, restrictions apply\n";
static char typeok[] = "200 Type %s OK\n";
static char only8[] = "501 Only logical bytesize 8 supported\n";
static char deleok[] = "250 File deleted\n";
static char mkdok[] = "200 MKD ok\n";
static char delefail[] = "550 Delete failed: %s\n";
static char pwdmsg[] = "257 \"%s\" is current directory\n";
static char badtype[] = "501 Unknown type \"%s\"\n";
static char badport[] = "501 Bad port syntax\n";
static char unimp[] = "502 Command not yet implemented\n";
static char bye[] = "221 Goodbye!\n";
static char nodir[] = "553 Can't read directory \"%s\": %s\n";
static char cantopen[] = "550 Can't read file \"%s\": %s\n";
static char sending[] = "150 Opening data connection for %s %s %s\n"; /*N1BEE*/
static char cantmake[] = "553 Can't create \"%s\": %s\n";
static char writerr[] = "552 Write error: %s\n";
static char portok[] = "200 Port command okay\n";
static char rxok[] = "226 File received OK\n";
static char txok[] = "226 File sent OK\n";
static char noperm[] = "550 Permission denied\n";
static char noconn[] = "425 Data connection reset\n";
static char badcheck[] = "425 Bad checksum\n";
static char lowmem[] = "421 System overloaded, try again later\n";
static char notlog[] = "530 Please log in with USER and PASS\n";
static char userfirst[] = "503 Login with USER first.\n";
static char okay[] = "200 Ok\n";
static char syst[] = "215 %s Type: L8 Version: %s\n";
#ifdef LZW
static char LZWOk[] = "299 %d %d LZW OK\n";
extern int Ftpslzw;
extern int Ftpclzw;
#endif
int32 Ftptdiscinit;
/* Set ftp redundancy timer */
int
doftptdisc(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong(&Ftptdiscinit,"Ftp redundancy timer (sec)",argc,argv);
}
/* Start up FTP service */
int
ftpstart(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int16 port;
if(argc < 2)
port = IPPORT_FTP;
else
port = atoi(argv[1]);
#ifdef LZW
/* Both the Server and Client will default to trying to */
/* use lzw compressiom. */
Ftpslzw = 1;
Ftpclzw = 1;
#endif
return start_tcp(port,"FTP Server",ftpserv,2048);
}
static void sendmsgfile(int s,int num,char *buf,int size,FILE *fp) {
while(fgets(buf,size,fp)) {
rip(buf);
usprintf(s,"%d- %s\n",num,buf);
}
}
static void
ftpserv(s,unused,p)
int s; /* Socket with user connection */
void *unused;
void *p;
{
struct ftpserv ftp;
char **cmdp,buf[512],*arg,*cp,*file,*mode;
long t;
int cnt,i;
struct sockaddr_in socket;
FILE *fp,*fpm;
sockmode(s,SOCK_ASCII);
memset((char *)&ftp,0,sizeof(ftp)); /* Start with clear slate */
ftp.data = -1;
sockowner(s,Curproc); /* We own it now */
ftp.control = s;
/* Set default data port */
i = SOCKSIZE;
getpeername(s,(char *)&socket,&i);
socket.sin_port = IPPORT_FTPD;
ASSIGN(ftp.port,socket);
#ifdef LZW
/* Socket assumes that lzw is off for socket. */
ftp.uselzw = 0;
#endif
log(s,"open FTP");
FtpUsers++;
/* now go say 'hello' */
usprintf(s,banner,Hostname,Version);
if((fp = fopen(Ftpmotd,"r")) != NULL) {
while(fgets(buf,128,fp)) {
rip(buf);
usprintf(s,"220- %s\n",buf);
}
fclose(fp);
}
time(&t);
cp = ctime(&t);
usprintf(s,banner1,cp);
loop:
/* Time-out after some inactivity time - WG7J */
alarm((long)(Ftptdiscinit*1000L));
if((cnt = recvline(s,buf,sizeof(buf))) == -1){
/* He closed on us */
goto finish;
}
alarm(0L);
if(cnt == 0){
/* Can't be a legal FTP command */
usputs(ftp.control,badcmd);
goto loop;
}
rip(buf);
/* Translate first word to lower case */
for(cp = buf;*cp != ' ' && *cp != '\0';cp++)
*cp = tolower(*cp);
/* Find command in table; if not present, return syntax error */
for(cmdp = commands;*cmdp != NULLCHAR;cmdp++)
if(strncmp(*cmdp,buf,strlen(*cmdp)) == 0)
break;
if(*cmdp == NULLCHAR){
usputs(ftp.control,badcmd);
goto loop;
}
/* Allow only USER, PASS and QUIT before logging in */
if(ftp.cd == NULLCHAR || ftp.path == NULLCHAR){
switch(cmdp-commands){
case USER_CMD:
case PASS_CMD:
case QUIT_CMD:
break;
default:
usputs(ftp.control,notlog);
goto loop;
}
}
arg = &buf[strlen(*cmdp)];
while(*arg == ' ')
arg++;
/* Execute specific command */
switch(cmdp-commands){
#ifdef LZW
case LZW_CMD:
if(!Ftpslzw) {
/* if the server doens't want to use LZW compression, issue
* the bad command message.
*/
usputs(ftp.control,badcmd);
ftp.uselzw = 0;
} else {
/* Get bits and mode from clients XLZW request. */
ftp.lzwmode = ftp.lzwbits = 0;
sscanf(arg,"%d %d",&ftp.lzwbits,&ftp.lzwmode);
if(!((ftp.lzwmode == 0 || ftp.lzwmode == 1)
&& (ftp.lzwbits > 8 && ftp.lzwbits < 17))) {
/* bad args... DON'T use LZW and tell the client. */
ftp.lzwmode = LZWCOMPACT;
ftp.lzwbits = LZWBITS;
usputs(ftp.control,badcmd);
ftp.uselzw = 0;
} else {
/* Tell the client that the command was accepted. */
usprintf(ftp.control,LZWOk,ftp.lzwbits,ftp.lzwmode);
/* And set the uselzw flag on the FTP socket struct. */
ftp.uselzw = 1;
}
}
break;
#endif /* LZW */
case USER_CMD:
free(ftp.username);
ftp.username = strdup(arg);
free(ftp.cd); /* In case another 'user' command is issued - WG7J */
free(ftp.path);
ftp.cd = NULL;
ftp.path = NULL;
/* See if this would be an anonymous login */
{
int anony = 0;
char *path;
path = mallocw(200);
userlogin(ftp.username,NULL,&path,200,&anony);
if(anony)
usputs(ftp.control,AnonymousLogin);
free(path);
}
usputs(ftp.control,givepass);
break;
case TYPE_CMD:
switch(arg[0]){
case 'A':
case 'a': /* Ascii */
ftp.type = ASCII_TYPE;
usprintf(ftp.control,typeok,arg);
break;
case 'l':
case 'L':
while(*arg != ' ' && *arg != '\0')
arg++;
if(*arg == '\0' || *++arg != '8'){
usputs(ftp.control,only8);
break;
}
ftp.type = LOGICAL_TYPE;
ftp.logbsize = 8;
usprintf(ftp.control,typeok,arg);
break;
case 'B':
case 'b': /* Binary */
case 'I':
case 'i': /* Image */
ftp.type = IMAGE_TYPE;
usprintf(ftp.control,typeok,arg);
break;
default: /* Invalid */
usprintf(ftp.control,badtype,arg);
break;
}
break;
case QUIT_CMD:
usputs(ftp.control,bye);
goto finish;
case RETR_CMD:
case RSME_CMD:
file = pathname(ftp.cd,arg);
switch(ftp.type){
case IMAGE_TYPE:
case LOGICAL_TYPE:
mode = READ_BINARY;
break;
case ASCII_TYPE:
mode = READ_TEXT;
break;
}
if(!permcheck(ftp.path,RETR_CMD,file)){
usputs(ftp.control,noperm);
} else if((ftp.fp = fopen(file,mode)) == NULLFILE){
usprintf(ftp.control,cantopen,file,sys_errlist[errno]);
} else {
if((cmdp-commands) == RSME_CMD) {
log(ftp.control,"RSME %s",file);
if(ftp.type == ASCII_TYPE && isbinary(ftp.fp)){
usprintf(ftp.control,binwarn,file);
}
sendit(&ftp,"RSME",file);
} else {
log(ftp.control,"RETR %s",file);
if(ftp.type == ASCII_TYPE && isbinary(ftp.fp)){
usprintf(ftp.control,binwarn,file);
}
sendit(&ftp,"RETR",file);
}
}
free(file);
break;
case STOR_CMD:
case RPUT_CMD:
file = pathname(ftp.cd,arg);
switch(ftp.type){
case IMAGE_TYPE:
case LOGICAL_TYPE:
if(cmdp-commands == RPUT_CMD)
mode = APPEND_BINARY;
else
mode = WRITE_BINARY;
break;
case ASCII_TYPE:
if(cmdp-commands == RPUT_CMD)
mode = APPEND_TEXT;
else
mode = WRITE_TEXT;
break;
}
if(cmdp-commands == RPUT_CMD){
if(!permcheck(ftp.path,RPUT_CMD,file)){
usputs(ftp.control,noperm);
} else if((ftp.fp = fopen(file,mode)) == NULLFILE){
usprintf(ftp.control,cantmake,file,sys_errlist[errno]);
} else {
log(ftp.control,"RPUT %s",file);
recvit(&ftp,"RPUT",file);
}
} else {
if(!permcheck(ftp.path,STOR_CMD,file)){
usputs(ftp.control,noperm);
} else if((ftp.fp = fopen(file,mode)) == NULLFILE){
usprintf(ftp.control,cantmake,file,sys_errlist[errno]);
} else {
log(ftp.control,"STOR %s",file);
recvit(&ftp,"STOR",file);
}
}
free(file);
break;
case PORT_CMD:
if(pport(&ftp.port,arg) == -1){
usputs(ftp.control,badport);
} else {
usputs(ftp.control,portok);
}
break;
#ifndef CPM
case LIST_CMD:
file = pathname(ftp.cd,arg);
if(!permcheck(ftp.path,RETR_CMD,file)){
usputs(ftp.control,noperm);
} else if((ftp.fp = dir(file,1)) == NULLFILE){
usprintf(ftp.control,nodir,file,sys_errlist[errno]);
} else {
sendit(&ftp,"LIST",file);
}
free(file);
break;
case NLST_CMD:
file = pathname(ftp.cd,arg);
if(!permcheck(ftp.path,RETR_CMD,file)){
usputs(ftp.control,noperm);
} else if((ftp.fp = dir(file,0)) == NULLFILE){
usprintf(ftp.control,nodir,file,sys_errlist[errno]);
} else {
sendit(&ftp,"NLST",file);
}
free(file);
break;
case CWD_CMD:
file = pathname(ftp.cd,arg);
if(!permcheck(ftp.path,RETR_CMD,file)){
usputs(ftp.control,noperm);
free(file);
#ifdef MSDOS
/* Don'tcha just LOVE %%$#@!! MS-DOS? */
} else if(strcmp(file,"/") == 0 || access(file,0) == 0){
#else
} else if(access(file,0) == 0){ /* See if it exists */
#endif
/* Succeeded, record in control block */
free(ftp.cd);
ftp.cd = file;
/* If exists, send the contents of 'desc.ftp' in the new
* directory...
*/
strcpy(buf,file);
if((fpm = fopen(strcat(buf,"/desc.ftp"),"r")) != NULL) {
sendmsgfile(ftp.control,257,buf,sizeof(buf),fpm);
fclose(fpm);
}
usprintf(ftp.control,pwdmsg,file);
} else {
/* Failed, don't change anything */
usprintf(ftp.control,nodir,file,sys_errlist[errno]);
free(file);
}
break;
case XPWD_CMD:
case PWD_CMD:
usprintf(ftp.control,pwdmsg,ftp.cd);
break;
#else
case LIST_CMD:
case NLST_CMD:
case CWD_CMD:
case XPWD_CMD:
case PWD_CMD:
#endif
case ACCT_CMD:
usputs(ftp.control,unimp);
break;
case DELE_CMD:
file = pathname(ftp.cd,arg);
if(!permcheck(ftp.path,DELE_CMD,file)){
usputs(ftp.control,noperm);
} else if(unlink(file) == 0){
log(ftp.control,"DELE %s",file);
usputs(ftp.control,deleok);
} else {
usprintf(ftp.control,delefail,sys_errlist[errno]);
}
free(file);
break;
case PASS_CMD:
if(ftp.username == NULLCHAR)
usputs(ftp.control,userfirst);
else
ftplogin(&ftp,arg);
break;
#ifndef CPM
case XMKD_CMD:
case MKD_CMD:
file = pathname(ftp.cd,arg);
if(!permcheck(ftp.path,MKD_CMD,file)){
usputs(ftp.control,noperm);
#ifdef UNIX
} else if(mkdir(file,0777) == 0){
#else
} else if(mkdir(file) == 0){
#endif
log(ftp.control,"MKD %s",file);
usputs(ftp.control,mkdok);
} else {
usprintf(ftp.control,cantmake,file,sys_errlist[errno]);
}
free(file);
break;
case XRMD_CMD:
case RMD_CMD:
file = pathname(ftp.cd,arg);
if(!permcheck(ftp.path,RMD_CMD,file)){
usputs(ftp.control,noperm);
} else if(rmdir(file) == 0){
log(ftp.control,"RMD %s",file);
usputs(ftp.control,deleok);
} else {
usprintf(ftp.control,delefail,sys_errlist[errno]);
}
free(file);
break;
case STRU_CMD:
if(tolower(arg[0]) != 'f')
usputs(ftp.control,unsupp);
else
usputs(ftp.control,okay);
break;
case MODE_CMD:
if(tolower(arg[0]) != 's')
usputs(ftp.control,unsupp);
else
usputs(ftp.control,okay);
break;
case SYST_CMD:
usprintf(ftp.control,syst,System,shortversion);
break;
}
#endif
goto loop;
finish:
FtpUsers--;
log(ftp.control,"close FTP");
/* Clean up */
close_s(ftp.control);
if(ftp.data != -1)
close_s(ftp.data);
if(ftp.fp != NULLFILE)
fclose(ftp.fp);
free(ftp.username);
free(ftp.path);
free(ftp.cd);
}
/* Shut down FTP server */
int
ftp0(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int16 port;
if(argc < 2)
port = IPPORT_FTP;
else
port = atoi(argv[1]);
return stop_tcp(port);
}
static
int
pport(sock,arg)
struct sockaddr_in *sock;
char *arg;
{
int32 n;
int i;
n = 0;
for(i=0;i<4;i++){
n = atoi(arg) + (n << 8);
if((arg = strchr(arg,',')) == NULLCHAR)
return -1;
arg++;
}
sock->sin_addr.s_addr = n;
n = atoi(arg);
if((arg = strchr(arg,',')) == NULLCHAR)
return -1;
arg++;
n = atoi(arg) + (n << 8);
sock->sin_port = n;
return 0;
}
/* Attempt to log in the user whose name is in ftp->username and password
* in pass
*/
static void
ftplogin(ftp,pass)
struct ftpserv *ftp;
char *pass;
{
char *path;
char *p;
int len,anony = 0;
FILE *fp;
char buf[128];
path = mallocw(200);
if(userlogin(ftp->username,pass,&path,200,&anony) == -1) {
usputs(ftp->control,noperm);
free(path);
return;
}
/* Set up current directory and path prefix */
ftp->path = strdup(path);
ftp->cd = firstpath(path);
free(path);
strcpy(buf,ftp->cd);
/* If path ends on /, cut if off; this allows the message to be
* send when login is to the root dir - WG7J
*/
len = strlen(buf);
if(buf[len-1] == '/')
buf[len-1] = '\0';
if((fp = fopen(strcat(buf,"/message.ftp"),"r")) != NULL) {
sendmsgfile(ftp->control,230,buf,sizeof(buf),fp);
fclose(fp);
}
if(!anony){
usputs(ftp->control,logged);
log(ftp->control,"%s logged in",ftp->username);
} else {
usputs(ftp->control,loggeda);
log(ftp->control,"%s logged in, ID %s",ftp->username,pass);
}
}
static int
sendit(ftp,command,file)
struct ftpserv *ftp;
char *command;
char *file;
{
long total, starting;
unsigned long check;
struct sockaddr_in dport;
char *cp;
char fsizetext[20] = ""; /* N1BEE */
ftp->data = socket(AF_INET,SOCK_STREAM,0);
dport.sin_family = AF_INET;
dport.sin_addr.s_addr = INADDR_ANY;
dport.sin_port = IPPORT_FTPD;
bind(ftp->data,(char *)&dport,SOCKSIZE);
sprintf(fsizetext, "(%lu bytes)", filelength(fileno(ftp->fp)));
usprintf(ftp->control,sending,command,file,fsizetext); /* N1BEE */
if(connect(ftp->data,(char *)&ftp->port,SOCKSIZE) == -1){
fclose(ftp->fp);
ftp->fp = NULLFILE;
close_s(ftp->data);
ftp->data = -1;
usputs(ftp->control,noconn);
return -1;
}
#ifdef LZW
if(ftp->uselzw == 1)
/* do lzwinit() for socket. */
lzwinit(ftp->data,ftp->lzwbits,ftp->lzwmode);
#endif
if(strcmp(command,"RSME") == 0) {
cp = mallocw(40);
recvline(ftp->control,cp,40);
starting = atol(cp);
/* If checksum field is not present go on anyway, for compatibility
* with previous scheme. If present check it and barf if wrong.
*/
if(strchr(cp,' ') != NULL){
check = (unsigned long)atol(strchr(cp,' '));
check -= checksum(ftp->fp,starting);
if(check != 0){
free(cp);
usputs(ftp->control,badcheck);
shutdown(ftp->data,1); /* Blow away data connection */
goto send_err;
}
} else if(fseek(ftp->fp,starting,SEEK_SET) != 0) {
free(cp);
usputs(ftp->control,noconn);
shutdown(ftp->data,2); /* Blow away data connection */
goto send_err;
}
}
/* Do the actual transfer */
total = sendfile(ftp->fp,ftp->data,ftp->type,0,NULL);
if(total == -1){
/* An error occurred on the data connection */
usputs(ftp->control,noconn);
shutdown(ftp->data,2); /* Blow away data connection */
} else {
usputs(ftp->control,txok);
}
send_err: fclose(ftp->fp);
ftp->fp = NULLFILE;
close_s(ftp->data);
ftp->data = -1;
#ifdef LZW
/* Done with data socket. Turn off lzw for now */
ftp->uselzw = 0;
#endif
if(total == -1)
return -1;
else
return 0;
}
static int
recvit(ftp,command,file)
struct ftpserv *ftp;
char *command;
char *file;
{
struct sockaddr_in dport;
long total, starting;
ftp->data = socket(AF_INET,SOCK_STREAM,0);
dport.sin_family = AF_INET;
dport.sin_addr.s_addr = INADDR_ANY;
dport.sin_port = IPPORT_FTPD;
bind(ftp->data,(char *)&dport,SOCKSIZE);
usprintf(ftp->control,sending,command,file,"");
if(connect(ftp->data,(char *)&ftp->port,SOCKSIZE) == -1){
fclose(ftp->fp);
ftp->fp = NULLFILE;
close_s(ftp->data);
ftp->data = -1;
usputs(ftp->control,noconn);
return -1;
}
#ifdef LZW
if(ftp->uselzw == 1)
/* do lzwinit() for socket. */
lzwinit(ftp->data,ftp->lzwbits,ftp->lzwmode);
#endif
if(strcmp(command,"RPUT") == 0){
if((starting = getsize(ftp->fp)) == -1)
starting = 0L;
usprintf(ftp->control,"%ld %lu\n",starting,checksum(ftp->fp,starting));
fseek(ftp->fp,starting,SEEK_SET);
}
total = recvfile(ftp->fp,ftp->data,ftp->type,0);
#ifdef CPM
if(ftp->type == ASCII_TYPE)
putc(CTLZ,ftp->fp);
#endif
if(total == -1) {
/* An error occurred while writing the file */
usprintf(ftp->control,writerr,sys_errlist[errno]);
shutdown(ftp->data,2); /* Blow it away */
} else
usputs(ftp->control,rxok);
close_s(ftp->data);
ftp->data = -1;
fclose(ftp->fp);
ftp->fp = NULLFILE;
#ifdef LZW
/* Done with data socket. Turn off lzw for now */
ftp->uselzw = 0;
#endif
if(total == -1)
return -1;
else
return 0;
}
#endif /* FTPSERVER */
#ifdef MSDOS
/* Illegal characters in a DOS filename */
static char badchars[] = "\"[]|<>+=;,";
#endif
/* Return 1 if the file operation is allowed, 0 otherwise */
int
permcheck(path,op,file)
char *path;
int op;
char *file;
{
char *cp,*privs;
long perms;
if(file == NULLCHAR || path == NULLCHAR)
return 0; /* Probably hasn't logged in yet */
#ifdef MSDOS
/* Check for characters illegal in MS-DOS file names */
#ifdef notdef
for(cp = file;*cp != '\0';cp++){
if(*cp != '\\' && *cp != '/' && *cp != '.' && *cp != ':'
&& *cp != '?' && *cp != '*' && dosfnchr(*cp) == 0)
return 0;
}
#endif
if(strpbrk(file,badchars) != NULLCHAR)
return 0;
#endif
#ifndef MAC
/* The target file must be under the user's allowed search path */
/* We let them specify multiple paths using path;path... -russ */
/* Now full form: path[;path...] perm path[;path...] perm ... */
{
int pathlen;
for(cp = path;;){
/* Make sure format is valid, privs field should be present! */
if((privs=strpbrk(cp," \t")) == NULLCHAR)
return 0;
/* Find length of path */
pathlen = strcspn(cp,"; \t");
while(pathlen) {
/* Check filename with path */
if(strncmp(file,cp,pathlen) == 0 && (
/* Some path validation */
file[pathlen] == '\0' ||
file[pathlen] == '/' ||
file[pathlen-1] == '/'))
break;
/* Check next path */
cp += pathlen;
if(*cp == ';') /* There is more in this compound path ! */
pathlen = strcspn(++cp,"; \t");
else
pathlen = 0;
}
if(pathlen) /* we found a match, no check privs */
break;
/* now see if there is more after the privs... */
privs = skipwhite(privs);
if((cp = strpbrk(privs," \t")) == NULL)
return 0; /* Nothing there ! */
/* skip spaces or tabs to get start of next 'path perm' entry */
cp = skipwhite(cp);
}
}
#endif
/* Now find start of privs */
privs = skipwhite(privs);
if(strnicmp(privs,"0x",2) == 0)
perms = htol(privs);
else
perms = atol(privs);
switch(op){
case RETR_CMD:
/* User must have permission to read files */
if(perms & FTP_READ)
return 1;
return 0;
case DELE_CMD:
case RMD_CMD:
case RPUT_CMD:
/* User must have permission to (over)write files */
if(perms & FTP_WRITE)
return 1;
return 0;
case STOR_CMD:
case MKD_CMD:
/* User must have permission to (over)write files, or permission
* to create them if the file doesn't already exist
*/
if(perms & FTP_WRITE)
return 1;
if(access(file,2) == -1 && (perms & FTP_CREATE))
return 1;
return 0;
}
return 0; /* "can't happen" -- keep lint happy */
}